﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CCWin;
using CCWin.SkinControl;
using System.Runtime.InteropServices;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using ESPlus.Rapid;
using GG.Core;
using ESBasic.ObjectManagement.Forms;
using ESPlus.Application.P2PSession.Passive;
using ESPlus.FileTransceiver;
using ESBasic;
using ImageCapturerLib;
using OMCS.Passive;
using GGLib;
using GGLib.NDisk.Passive;
using GGLib.Core;
using GGLib.NDisk;

namespace GG
{
    public partial class ChatForm : CCSkinMain ,IManagedForm<string>
    {
        private INDiskOutter nDiskOutter; // V2.0 
        private IMultimediaManager multimediaManager;
        private VideoForm videoForm = null;
        private RemoteHelpForm remoteHelpForm = null;
        private string Title_FileTransfer = "文件传送";
        private string Title_Video = "视频";
        private string Title_Disk = "磁盘";
        private string Title_RemoteHelp = "远程协助";
        private string Title_RemoteHelpHandle = "桌面共享";
        private FileTransferingViewer fileTransferingViewer = new FileTransferingViewer();
        private VideoRequestPanel videoRequestPanel = new VideoRequestPanel();
        private DiskRequestPanel diskRequestPanel = new DiskRequestPanel();
        private RemoteHelpRequestPanel remoteHelpRequestPanel = new RemoteHelpRequestPanel();
        private RemoteHelpHandlePanel remoteHelpHandlePanel = new RemoteHelpHandlePanel();
        private EmotionForm emotionForm;
        private IRapidPassiveEngine rapidPassiveEngine;
       
        private bool friendOffline = false;
        private string myNickName = "";
        private string friendNickName = "";
        private string friendID = "";          
       
        #region IManagedForm Member
        public string FormID
        {
            get { return this.friendID; }
        } 
        #endregion

        #region Ctor
        public ChatForm(IRapidPassiveEngine engine, IMultimediaManager mgr, INDiskOutter diskOutter, string _myNickName, ChatListSubItem item)
        {
            this.rapidPassiveEngine = engine;
            this.multimediaManager = mgr;
            this.nDiskOutter = diskOutter;
            this.myNickName = _myNickName;
            this.friendNickName = item.DisplayName;
            this.friendID = item.NicName;
            InitializeComponent();

            this.Text = "与 " + this.friendNickName + " 对话中";
            this.labelFriendName.Text = friendNickName;
            this.labelFriendSignature.Text = item.PersonalMsg;
            this.panelFriendHeadImage.BackgroundImage = item.HeadImage;
            this.textBoxSend.Focus();

            List<Image> emotionList = new List<Image>();
            foreach (Image emotion in this.imageList1.Images)
            {
                emotionList.Add(emotion);
            }

            this.emotionForm = new EmotionForm();
            this.emotionForm.Load += new EventHandler(emotionForm_Load);
            this.emotionForm.Initialize(emotionList);
            this.emotionForm.EmotionClicked += new ESBasic.CbGeneric<Image>(emotionForm_Clicked);
            this.emotionForm.Visible = false;

            this.rapidPassiveEngine.ConnectionInterrupted += new CbGeneric(rapidPassiveEngine_ConnectionInterrupted);
            this.rapidPassiveEngine.P2PController.P2PChannelOpened += new CbGeneric<P2PChannelState>(P2PController_P2PChannelOpened);
            this.rapidPassiveEngine.P2PController.P2PChannelClosed += new CbGeneric<P2PChannelState>(P2PController_P2PChannelClosed);

            //文件传送
            this.fileTransferingViewer.Initialize(this.friendID, this.rapidPassiveEngine.FileOutter, delegate(TransferingProject pro) { return Comment4NDisk.ParseDirectoryPath(pro.Comment) == null; });
            this.fileTransferingViewer.FileTransDisruptted += new CbGeneric<string, bool, FileTransDisrupttedType>(fileTransferingViewer1_FileTransDisruptted);
            this.fileTransferingViewer.FileTransCompleted += new CbGeneric<string, bool ,string>(fileTransferingViewer1_FileTransCompleted);
            this.fileTransferingViewer.FileResumedTransStarted += new CbGeneric<string, bool>(fileTransferingViewer1_FileResumedTransStarted);
            this.fileTransferingViewer.AllTaskFinished += new CbSimple(fileTransferingViewer1_AllTaskFinished);

            //视频
            this.videoRequestPanel.VideoRequestAnswerd += new CbGeneric<bool>(videoRequestPanel_VideoRequestAnswerd);
            //磁盘 V2.0
            this.diskRequestPanel.DiskRequestAnswerd += new CbGeneric<bool>(diskRequestPanel_DiskRequestAnswerd);
            //远程协助 V2.2
            this.remoteHelpRequestPanel.RemoteHelpRequestAnswerd += new CbGeneric<bool>(remoteHelpRequestPanel_RemoteHelpRequestAnswerd);
            this.remoteHelpHandlePanel.RemoteHelpTerminated += new CbGeneric(remoteHelpHandlePanel_RemoteHelpTerminated);
            this.ShowP2PState();
        }        

        void emotionForm_Load(object sender, EventArgs e)
        {
            this.emotionForm.Location = new Point((this.Left + 30) - (this.emotionForm.Width / 2), this.Top + this.skinPanel_left.Top + skToolMenu.Top - this.emotionForm.Height);
        }

        void emotionForm_Clicked(Image img)
        {
            this.textBoxSend.InsertImage(img);
            this.emotionForm.Visible = false;
        } 
        #endregion

        #region P2P 通道状态
        void P2PController_P2PChannelClosed(P2PChannelState state)
        {
            this.ShowP2PState();
        }

        void P2PController_P2PChannelOpened(P2PChannelState state)
        {
            this.ShowP2PState();
        }

        public void ShowP2PState()
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new CbGeneric(this.ShowP2PState));
            }
            else
            {
                P2PChannelState state = this.rapidPassiveEngine.P2PController.GetP2PChannelState(this.friendID);
                if (state != null)
                {
                    this.Text = string.Format("与 {0} 对话中...【P2P直连/{1}】", this.friendNickName, state.ProtocolType);
                    this.skinLabel_p2PState.Text = string.Format("P2P直连/{0}", state.ProtocolType);
                    this.pictureBox_state.Visible = true;
                }
                else
                {
                    this.Text = string.Format("与 {0} 对话中...", this.friendNickName);
                    this.skinLabel_p2PState.Text = "";
                    this.pictureBox_state.Visible = false;
                }
            }
        }
        #endregion

        #region 自己掉线，好友掉线
        void rapidPassiveEngine_ConnectionInterrupted()
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new CbGeneric(this.rapidPassiveEngine_ConnectionInterrupted));
            }
            else
            {
                this.OnOffline(true);
            }
        }

        /// <summary>
        /// 好友掉线
        /// </summary>
        public void FriendOffline()
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new CbGeneric(this.FriendOffline));
            }
            else
            {
                this.friendOffline = true;
                this.OnOffline(false);
            }
        }

        private void OnOffline(bool myself)
        {
            string tip = string.Format("{0}已经掉线。", myself ? "自己" : "对方");
            this.AppendSysMessage(tip);

            if (this.videoForm != null)
            {
                this.videoForm.OnHungUpVideo();
                string msg = string.Format("{0}已经掉线，与对方的视频会话中止。" ,myself? "自己" : "对方");
                this.AppendSysMessage(msg);
            }

            if (this.TabControlContains(this.Title_Disk))
            {
                this.skinTabControl1.TabPages.RemoveAt(this.GetSelectIndex(this.Title_Disk));
                this.skinTabControl1.SelectedIndex = this.skinTabControl1.TabPages.Count - 1;
            }

            if (this.TabControlContains(this.Title_RemoteHelpHandle))
            {
                this.skinTabControl1.TabPages.RemoveAt(this.GetSelectIndex(this.Title_RemoteHelpHandle));
                this.skinTabControl1.SelectedIndex = this.skinTabControl1.TabPages.Count - 1;                
            }

            if (this.TabControlContains(this.Title_RemoteHelp))
            {
                this.skinTabControl1.TabPages.RemoveAt(this.GetSelectIndex(this.Title_RemoteHelp));
                this.skinTabControl1.SelectedIndex = this.skinTabControl1.TabPages.Count - 1;
            }
        }
        #endregion        

        #region TabControlContains
        private bool TabControlContains(string text)
        {
            for (int i = 0; i < this.skinTabControl1.TabPages.Count; i++)
            {
                if (this.skinTabControl1.TabPages[i].Text == text)
                {
                    return true;
                }
            }
            return false;
        }
        #endregion

        #region GetSelectIndex
        private int GetSelectIndex(string text)
        {
            for (int i = 0; i < this.skinTabControl1.TabPages.Count; i++)
            {
                if (this.skinTabControl1.TabPages[i].Text == text)
                {
                    return i;
                }
            }
            return -1;
        }
        #endregion

        #region 文件传输

        #region 发送 传输文件的请求
        private void toolStripButton_fileTransfer_Click(object sender, EventArgs e)
        {
            try
            {
                string filePath = ESBasic.Helpers.FileHelper.GetFileToOpen("请选择要发送的文件");
                if (filePath == null)
                {
                    return;
                }
                string projectID;               
                SendingFileParas sendingFileParas = new SendingFileParas(2048, 0);//文件数据包大小，可以根据网络状况设定，局网内可以设为204800，传输速度可以达到30M/s以上；公网建议设定为2048或4096或8192
               
                this.rapidPassiveEngine.FileOutter.BeginSendFile(this.friendID, filePath, null, sendingFileParas, out projectID);
                this.FileRequestReceived(projectID);
            }
            catch (Exception ee)
            {                
                MessageBox.Show(ee.Message, "GG");
            }
        }

        private void toolStripMenuItem33_Click(object sender, EventArgs e)
        {
            try
            {
                string folderPath = ESBasic.Helpers.FileHelper.GetFolderToOpen(false);
                if (folderPath == null)
                {
                    return;
                }
                string projectID;
                SendingFileParas sendingFileParas = new SendingFileParas(2048, 0);//文件数据包大小，可以根据网络状况设定，局网内可以设为204800，传输速度可以达到30M/s以上；公网建议设定为2048或4096或8192

                this.rapidPassiveEngine.FileOutter.BeginSendFile(this.friendID, folderPath, null, sendingFileParas, out projectID);
                this.FileRequestReceived(projectID);
            }
            catch (Exception ee)
            {
                MessageBox.Show(ee.Message, "GG");
            }
        }  
        #endregion

        #region 收到文件传输请求
        /// <summary>
        /// 当收到文件传输请求的时候 ，展开fileTransferingViewer,如果 本来就是展开 状态，直接添加
        /// 自己发送 文件请求的时候，也调用这里
        /// </summary>        
        internal void FileRequestReceived(string projectID ,bool offlineFile)
        {
            if (!this.TabControlContains(this.Title_FileTransfer))
            {               
                TabPage page = new TabPage(this.Title_FileTransfer);
                page.BackColor = Color.FromArgb(244, 249, 252);// System.Drawing.Color.White;
                Panel pannel = new Panel();               
                page.Controls.Add(pannel);
                pannel.BackColor = Color.Transparent;
                pannel.Dock = DockStyle.Fill;
                pannel.Controls.Add(this.fileTransferingViewer);
                this.fileTransferingViewer.Dock = System.Windows.Forms.DockStyle.Fill;
                this.skinTabControl1.TabPages.Add(page);
                this.skinTabControl1.SelectedIndex = this.GetSelectIndex(this.Title_FileTransfer);
            }
            this.fileTransferingViewer.NewFileTransferItem(projectID, offlineFile);            
        }

        internal void FileRequestReceived(string projectID)
        {
            this.FileRequestReceived(projectID, false);
        }
        #endregion     

        #region fileTransferingViewer1_FileTransDisruptted
        /// <summary>
        /// 文件传输失败
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="isSender">是接收者，还是发送者</param>
        /// <param name="fileTransDisrupttedType">失败原因</param>
        private void fileTransferingViewer1_FileTransDisruptted(string projectName, bool isSender, FileTransDisrupttedType fileTransDisrupttedType)
        {          
            string showText = "";
            switch (fileTransDisrupttedType)
            {
                case FileTransDisrupttedType.RejectAccepting:
                    {
                        if (isSender)
                        {
                            showText += string.Format("'{0}'传送失败！{1}", projectName, "对方拒绝接收文件。");
                        }
                        else
                        {
                            showText += string.Format("'{0}'传送失败！{1}", projectName, "您拒绝接收文件。");
                        }
                        break;
                    }
                case FileTransDisrupttedType.ActiveCancel:
                    {
                        if (isSender)
                        {
                            showText += string.Format("'{0}'传送失败！{1}", projectName, "您取消发送文件。");
                        }
                        else
                        {
                            showText += string.Format("'{0}'传送失败！{1}", projectName, "您取消接收文件。");
                        }
                        break;
                    }
                case FileTransDisrupttedType.DestCancel:
                    {
                        if (isSender)
                        {
                            showText += string.Format("'{0}'传送失败！{1}", projectName, "对方取消接收文件。");
                        }
                        else
                        {
                            showText += string.Format("'{0}'传送失败！{1}", projectName, "对方取消发送文件。");
                        }

                        break;
                    }
                case FileTransDisrupttedType.DestOffline:
                    {
                        showText += string.Format("'{0}'传送失败！{1}", projectName, "对方掉线！");
                        break;
                    }
                case FileTransDisrupttedType.SelfOffline:
                    {
                        showText += string.Format("'{0}'传送失败！{1}", projectName, "您已经掉线！");
                        break;
                    }
                case FileTransDisrupttedType.DestInnerError:
                    {
                        showText += string.Format("'{0}'传送失败！{1}", projectName, "对方系统内部错误。");
                        break;
                    }
                case FileTransDisrupttedType.InnerError:
                    {
                        showText += string.Format("'{0}'传送失败！{1}", projectName, "本地系统内部错误。");
                        break;
                    }
                case FileTransDisrupttedType.ReliableP2PChannelClosed:
                    {
                        showText += string.Format("'{0}'传送失败！{1}", projectName, "与对方可靠的P2P通道已经关闭。");
                        break;
                    }

            }
            this.AppendSysMessage(showText);
            //this.AppendMessage("系统", RtfRichTextBox.RtfColor.Gray, showText, false);      
        }
        #endregion

        #region fileTransferingViewer1_FileResumedTransStarted
        /// <summary>
        /// 文件续传
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="isSender">接收者，还是发送者</param>
        private void fileTransferingViewer1_FileResumedTransStarted(string projectName, bool isSender)
        {
            string showText = string.Format("正在续传文件 '{0}'...", projectName);
            this.AppendSysMessage(showText);            
        }
        #endregion

        #region fileTransferingViewer1_FileTransCompleted
        /// <summary>
        /// 文件传输成功
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="isSender">接收者，还是发送者</param>
        private void fileTransferingViewer1_FileTransCompleted(string projectName, bool isSender, string comment)
        {
            string offlineFile = (Comment4OfflineFile.ParseUserID(comment) == null) ? "" : "离线文件";
            string showText = offlineFile + string.Format("'{0}' {1}完成！", projectName, isSender ? "发送" :"接收");
            this.AppendSysMessage(showText);                   
        }
        #endregion

        #region AppendMessage
        private void AppendMessage(string userName, RtfRichTextBox.RtfColor color, string msg, bool isRtf)
        {
            this.AppendMessage(userName, color, null, msg, isRtf);
        }
        private void AppendMessage(string userName, RtfRichTextBox.RtfColor color, DateTime? originTime, string msg, bool isRtf)
        {
            DateTime showTime = DateTime.Now;
            this.rtfRichTextBox_history.AppendTextAsRtf(string.Format("{0}  {1}\n", userName, showTime), new Font(this.Font, FontStyle.Regular), color);
            if (originTime != null)
            {
                this.rtfRichTextBox_history.AppendText(string.Format("[{0} 离线消息] " ,originTime.Value.ToLongTimeString()));
            }

            if (isRtf)
            {
                this.rtfRichTextBox_history.AppendRtf(msg);
            }
            else
            {
                this.rtfRichTextBox_history.AppendText(msg);
            }            
            this.rtfRichTextBox_history.Select(this.rtfRichTextBox_history.Text.Length, 0);
            this.rtfRichTextBox_history.ScrollToCaret();
        }

        public void AppendSysMessage(string msg)
        {
            this.AppendMessage("系统", RtfRichTextBox.RtfColor.Gray,null, msg, false);
            this.rtfRichTextBox_history.AppendText("\n");
        }
        #endregion

        #region fileTransferingViewer1_AllTaskFinished
        private void fileTransferingViewer1_AllTaskFinished()
        {
            this.skinTabControl1.TabPages.RemoveAt(this.GetSelectIndex(this.Title_FileTransfer));
            this.skinTabControl1.SelectedIndex = this.skinTabControl1.TabPages.Count - 1;
        }
        #endregion
        #endregion               

        #region FriendOnline
        /// <summary>
        /// 好友上线
        /// </summary>
        public void FriendOnline()
        {
            this.friendOffline = false;
        }
        #endregion         

        #region 文字聊天
        #region FlashChatWindow
        [DllImport("User32")]
        public static extern bool FlashWindow(IntPtr hWnd, bool bInvert);
        public void FlashChatWindow()
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                int MyTimes = 4;
                int MyTime = 500;
                for (int MyCount = 0; MyCount < MyTimes; MyCount++)
                {
                    FlashWindow(this.Handle, true);
                    System.Threading.Thread.Sleep(MyTime);
                }
            }
            else
            {
                this.Show();
                this.Focus();
            }
        }
        #endregion

        #region 发送
        //发送
        private void btnSend_Click(object sender, EventArgs e)
        {
            if (this.textBoxSend.Text == "")
            {
                return;
            }

            try
            {
                byte[] buff = System.Text.Encoding.UTF8.GetBytes(this.textBoxSend.Rtf);
                this.rapidPassiveEngine.CustomizeOutter.Send(this.friendID, InformationTypes.Chat, buff);
                this.AppendMessage(this.myNickName, RtfRichTextBox.RtfColor.Green, this.textBoxSend.Rtf, true);

                //清空输入框
                this.textBoxSend.Text = string.Empty;
                this.textBoxSend.Focus();
            }
            catch
            {
                this.rtfRichTextBox_history.AppendText(DateTime.Now.ToLongTimeString() + " 发送消息失败！");
            }
        }
        #endregion

        #region 字体
        //显示字体对话框
        private void toolFont_Click(object sender, EventArgs e)
        {
            this.fontDialog1.Font = this.textBoxSend.Font;
            this.fontDialog1.Color = this.textBoxSend.ForeColor;
            if (DialogResult.OK == this.fontDialog1.ShowDialog())
            {
                this.textBoxSend.Font = this.fontDialog1.Font;
                this.textBoxSend.ForeColor = this.fontDialog1.Color;
            }
        }
        #endregion

        #region Vibration 震动
        //震动方法
        private void Vibration()
        {
            Point pOld = this.Location;//原来的位置
            int radius = 3;//半径
            for (int n = 0; n < 3; n++) //旋转圈数
            {
                //右半圆逆时针
                for (int i = -radius; i <= radius; i++)
                {
                    int x = Convert.ToInt32(Math.Sqrt(radius * radius - i * i));
                    int y = -i;

                    this.Location = new Point(pOld.X + x, pOld.Y + y);
                    Thread.Sleep(10);
                }
                //左半圆逆时针
                for (int j = radius; j >= -radius; j--)
                {
                    int x = -Convert.ToInt32(Math.Sqrt(radius * radius - j * j));
                    int y = -j;

                    this.Location = new Point(pOld.X + x, pOld.Y + y);
                    Thread.Sleep(10);
                }
            }
            //抖动完成，恢复原来位置
            this.Location = pOld;
        }

        //震动
        private void toolVibration_Click(object sender, EventArgs e)
        {
            this.rapidPassiveEngine.CustomizeOutter.Send(this.friendID, InformationTypes.Vibration, null);
            this.AppendMessage(this.myNickName, RtfRichTextBox.RtfColor.Green, "您发送了一个窗口抖动。", false);

            this.textBoxSend.Text = string.Empty;
            this.textBoxSend.Focus();
            Vibration();
        }
        #endregion               

        public void OnReceivedMsg(string msg)
        {
            this.AppendMessage(this.friendNickName, RtfRichTextBox.RtfColor.Blue ,null, msg, true);
        }

        public void OnReceivedOfflineMessage(DateTime originTime, string msg)
        {
            this.AppendMessage(this.friendNickName, RtfRichTextBox.RtfColor.Blue, originTime, msg, true);
        }

        public void OnReceivedOfflineFileResultNotify(string fileName,bool accept)
        {
            string msg = string.Format("对方{0}了您发送的离线文件'{1}'", accept ? "已成功接收" : "拒绝", fileName);
            this.AppendSysMessage(msg);
        }

        public void OnViberation()
        {
            string msg = this.friendNickName + "给您发送了窗口抖动。";
            this.AppendMessage(this.friendNickName, RtfRichTextBox.RtfColor.Blue,null, msg, false);
            Vibration();
        } 
        #endregion

        #region 窗体事件
        //悬浮至好友Q名时
        private void labelFriendName_MouseEnter(object sender, EventArgs e)
        {
            this.labelFriendName.Font = new Font("微软雅黑", 14F, FontStyle.Underline);
        }

        //离开好友Q名时
        private void labelFriendName_MouseLeave(object sender, EventArgs e)
        {
            this.labelFriendName.Font = new Font("微软雅黑", 14F);
        }

        //渐变层
        private void FrmChat_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            SolidBrush sb = new SolidBrush(Color.FromArgb(100, 255, 255, 255));
            g.FillRectangle(sb, new Rectangle(new Point(1, 91), new Size(Width - 2, Height - 91)));
        }

        //窗体调用重绘时
        protected override void OnInvalidated(InvalidateEventArgs e)
        {
            rtfRichTextBox_history.Invalidate();
            textBoxSend.Invalidate();
            base.OnInvalidated(e);
        }

        private void ChatForm_SizeChanged(object sender, EventArgs e)
        {
            this.skinPanel_left.Height = this.Height - 100;
        }
        
        #endregion      

        #region 关闭窗体
        //关闭
        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void ChatForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.rapidPassiveEngine.ConnectionInterrupted -= new CbGeneric(rapidPassiveEngine_ConnectionInterrupted);
            this.rapidPassiveEngine.P2PController.P2PChannelOpened -= new CbGeneric<P2PChannelState>(P2PController_P2PChannelOpened);
            this.rapidPassiveEngine.P2PController.P2PChannelClosed -= new CbGeneric<P2PChannelState>(P2PController_P2PChannelClosed);

            this.emotionForm.Visible = false;
            this.emotionForm.Close();

            this.fileTransferingViewer.FileTransferingViewer_Disposed();
            e.Cancel = false;
        } 
        #endregion

        #region 截图
        private void buttonCapture_Click(object sender, EventArgs e)
        {
            ImageCapturer imageCapturer = new ImageCapturer();
            if (imageCapturer.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.textBoxSend.InsertImage(imageCapturer.Image);
                this.textBoxSend.Focus();
                this.textBoxSend.ScrollToCaret();
            }
        } 
        #endregion       

        #region 表情
        private void toolStripButtonEmotion_Click(object sender, EventArgs e)
        {
            this.emotionForm.Location = new Point((this.Left + 30) - (this.emotionForm.Width / 2), this.Top + this.skinPanel_left.Top + skToolMenu.Top - this.emotionForm.Height);
            this.emotionForm.Visible = !this.emotionForm.Visible;
        } 
        #endregion

        #region 手写板
        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            PaintForm form = new PaintForm();
            form.Location = new Point(this.Left + 20, this.Top + this.skinPanel_left.Top + skToolMenu.Top - form.Height);
            if (DialogResult.OK == form.ShowDialog())
            {
                Bitmap bitmap = form.CurrentImage;
                if (bitmap != null)
                {
                    this.textBoxSend.InsertImage(bitmap);
                    this.textBoxSend.Focus();
                    this.textBoxSend.ScrollToCaret();
                }
            }
        } 
        #endregion

        #region 视频聊天 V1.8
        //发出视频邀请
        private void toolStripDropDownButton1_ButtonClick(object sender, EventArgs e)
        {
            if (this.friendOffline)
            {
                return;
            }

            if (this.videoForm != null)
            {
                return;
            }

            this.rapidPassiveEngine.CustomizeOutter.Send(this.friendID, InformationTypes.VideoRequest, null);
            this.videoForm = new VideoForm(this.multimediaManager, this.rapidPassiveEngine.CurrentUserID, this.friendID, this.friendNickName, true);
            this.videoForm.FormClosed += new FormClosedEventHandler(videoForm_FormClosed);
            this.videoForm.ActiveHungUpVideo += new CbGeneric(videoForm_ActiveHungUpVideo);
            this.videoForm.Show();
        }

        /// <summary>
        /// 收到视频聊天的请求
        /// </summary>  
        internal void OnVideoRequestReceived()
        {
            if (!this.TabControlContains(this.Title_Video))
            {
                TabPage page = new TabPage(this.Title_Video);
                page.BackColor = Color.FromArgb(244, 249, 252);// System.Drawing.Color.White;
                Panel pannel = new Panel();
                page.Controls.Add(pannel);
                pannel.BackColor = Color.Transparent;
                pannel.Dock = DockStyle.Fill;
                pannel.Controls.Add(this.videoRequestPanel);
                this.fileTransferingViewer.Dock = System.Windows.Forms.DockStyle.Fill;
                this.skinTabControl1.TabPages.Add(page);
                this.skinTabControl1.SelectedIndex = this.GetSelectIndex(this.Title_Video);
            }            
        }        

        /// <summary>
        /// 对方回复视频邀请
        /// </summary>        
        internal void OnVideoAnswerReceived(bool agree)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new CbGeneric<bool>(this.OnVideoAnswerReceived), agree);
            }
            else
            {
                if (agree)
                {
                    this.videoForm.OnAgree();
                }
                else
                {
                    this.videoForm.Close();
                    this.videoForm = null;                   
                    this.AppendSysMessage("对方拒绝了您的视频邀请。") ;
                }
            }
        }

        /// <summary>
        /// 对方挂断了视频
        /// </summary>       
        internal void OnVideoHungUpReceived()
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new CbGeneric(this.OnVideoHungUpReceived));
            }
            else
            {
                if (this.videoForm != null)
                {
                    this.videoForm.OnHungUpVideo();
                    this.AppendSysMessage("对方中止了视频通话。");
                    return;
                }

                int tabIndex = this.GetSelectIndex(this.Title_Video);
                if (tabIndex >= 0)
                {
                    this.skinTabControl1.TabPages.RemoveAt(tabIndex);
                    this.skinTabControl1.SelectedIndex = this.skinTabControl1.TabPages.Count - 1;
                    this.AppendSysMessage("对方结束了视频会话邀请。");
                }
            }
        }        

        /// <summary>
        /// 作为视频接收方，对视频会话请求的应答。（点击控件的按钮）
        /// </summary>
        void videoRequestPanel_VideoRequestAnswerd(bool agree)
        {
            this.skinTabControl1.TabPages.RemoveAt(this.GetSelectIndex(this.Title_Video));
            this.skinTabControl1.SelectedIndex = this.skinTabControl1.TabPages.Count - 1;

            this.rapidPassiveEngine.CustomizeOutter.Send(this.friendID, agree ? InformationTypes.AgreeVideo : InformationTypes.RejectVideo, null);

            if (agree)
            {
                this.videoForm = new VideoForm(this.multimediaManager, this.rapidPassiveEngine.CurrentUserID, this.friendID, this.friendNickName, false);
                this.videoForm.FormClosed += new FormClosedEventHandler(videoForm_FormClosed);
                this.videoForm.ActiveHungUpVideo += new CbGeneric(videoForm_ActiveHungUpVideo);
                this.videoForm.Show();
            }
            else
            {
                string showText = "您拒绝了对方的视频邀请。";
                this.AppendSysMessage(showText);
            }
        }

        void videoForm_ActiveHungUpVideo()
        {
            this.rapidPassiveEngine.CustomizeOutter.Send(this.friendID, InformationTypes.HungUpVideo, null);
            this.AppendSysMessage("您中止了视频通话。");
        }

        void videoForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.videoForm = null;
        }
        #endregion        

        #region 远程磁盘 V2.0
        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            if (this.friendOffline)
            {
                return;
            }

            this.rapidPassiveEngine.CustomizeOutter.Send(this.friendID, InformationTypes.DiskRequest, null);
            this.AppendSysMessage("请求访问对方磁盘，正在等待对方回应...");
        }

        /// <summary>
        /// 作为远程磁盘的访问者，收到主人对磁盘访问请求的回应
        /// </summary>        
        internal void OnDiskAnswerReceived(bool agree)
        {
            if (!agree)
            {
                this.AppendSysMessage("对方拒绝了您的磁盘访问请求.");
                return;
            }

            this.AppendSysMessage("对方同意了您的磁盘访问请求.");
            NDiskForm form = new NDiskForm(this.friendID, this.friendNickName, this.rapidPassiveEngine.FileOutter, this.nDiskOutter);
            form.Show();
        }
       
        /// <summary>
        /// 作为磁盘的主人，收到磁盘访问的请求
        /// </summary>
        internal void OnDiskRequestReceived()
        {
            if (!this.TabControlContains(this.Title_Disk))
            {
                TabPage page = new TabPage(this.Title_Disk);
                page.BackColor = Color.FromArgb(244, 249, 252);// System.Drawing.Color.White;
                Panel pannel = new Panel();
                page.Controls.Add(pannel);
                pannel.BackColor = Color.Transparent;
                pannel.Dock = DockStyle.Fill;
                pannel.Controls.Add(this.diskRequestPanel);
                this.fileTransferingViewer.Dock = System.Windows.Forms.DockStyle.Fill;
                this.skinTabControl1.TabPages.Add(page);
                this.skinTabControl1.SelectedIndex = this.GetSelectIndex(this.Title_Disk);
            }
        }

        /// <summary>
        /// 作为磁盘的主人，对远程磁盘请求的应答。（点击控件的按钮）
        /// </summary>        
        void diskRequestPanel_DiskRequestAnswerd(bool agree)
        {
            this.skinTabControl1.TabPages.RemoveAt(this.GetSelectIndex(this.Title_Disk));
            this.skinTabControl1.SelectedIndex = this.skinTabControl1.TabPages.Count - 1;

            this.rapidPassiveEngine.CustomizeOutter.Send(this.friendID, agree ? InformationTypes.AgreeDisk : InformationTypes.RejectDisk, null);

            string showText = string.Format("您{0}了对方的磁盘访问请求。", agree ? "同意" : "拒绝");
            this.AppendSysMessage(showText);
        }
        #endregion    

        #region 远程协助 V2.2
        private void 请求远程协助ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.friendOffline)
            {
                return;
            }

            if (this.TabControlContains(this.Title_RemoteHelpHandle))
            {
                return;
            }

            this.multimediaManager.DesktopRegion = null; //设为null，表示共享整个屏幕
            this.PrepairRemoteHelp(null);
        }

        private void 桌面共享指定区域ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Visible = false;
            ESBasic.Widget.CaptureScreenForm form = new ESBasic.Widget.CaptureScreenForm();
            DialogResult res =form.ShowDialog() ;
            this.Visible = true;

            if (res != System.Windows.Forms.DialogResult.OK)
            {                
                return;
            }

            this.multimediaManager.DesktopRegion = form.CaptureRegion;
            this.PrepairRemoteHelp(form.CaptureRegion);
        }

        private void PrepairRemoteHelp(Rectangle? regionSelected)
        {
            this.rapidPassiveEngine.CustomizeOutter.Send(this.friendID, InformationTypes.RemoteHelpRequest, null);
            string msg = "请求对方远程协助自己，正在等待对方回应...";
            if (regionSelected != null)
            {
                msg = string.Format("已经指定共享桌面的区域{0}，并" ,regionSelected.Value) + msg;
            }
            this.AppendSysMessage(msg);

            TabPage page = new TabPage(this.Title_RemoteHelpHandle);
            page.BackColor = Color.FromArgb(244, 249, 252);// System.Drawing.Color.White;
            Panel pannel = new Panel();
            page.Controls.Add(pannel);
            pannel.BackColor = Color.Transparent;
            pannel.Dock = DockStyle.Fill;
            pannel.Controls.Add(this.remoteHelpHandlePanel);
            this.fileTransferingViewer.Dock = System.Windows.Forms.DockStyle.Fill;
            this.skinTabControl1.TabPages.Add(page);
            this.skinTabControl1.SelectedIndex = this.GetSelectIndex(this.Title_RemoteHelpHandle);
        }  

        /// <summary>
        /// 【站在请求方角度】对方回复远程协助请求
        /// </summary>        
        internal void OnRemoteHelpAnswerReceived(bool agree)
        {
            if (!agree)
            {
                this.AppendSysMessage("对方拒绝了您的远程协助请求.");
                this.skinTabControl1.TabPages.RemoveAt(this.GetSelectIndex(this.Title_RemoteHelpHandle));
                this.skinTabControl1.SelectedIndex = this.skinTabControl1.TabPages.Count - 1;
                return;
            }

            this.AppendSysMessage("对方同意了您的远程协助请求.");
            this.remoteHelpHandlePanel.OnAgree();
        }

        /// <summary>
        /// 【站在协助方角度】收到远程协助请求
        /// </summary>
        internal void OnRemoteHelpRequestReceived()
        {
            if (!this.TabControlContains(this.Title_RemoteHelp))
            {
                TabPage page = new TabPage(this.Title_RemoteHelp);
                page.BackColor = Color.FromArgb(244, 249, 252);// System.Drawing.Color.White;
                Panel pannel = new Panel();
                page.Controls.Add(pannel);
                pannel.BackColor = Color.Transparent;
                pannel.Dock = DockStyle.Fill;
                pannel.Controls.Add(this.remoteHelpRequestPanel);
                this.fileTransferingViewer.Dock = System.Windows.Forms.DockStyle.Fill;
                this.skinTabControl1.TabPages.Add(page);
                this.skinTabControl1.SelectedIndex = this.GetSelectIndex(this.Title_RemoteHelp);
            }
        }

        /// <summary>
        /// 【站在协助方角度】请求方终止了桌面共享
        /// </summary>
        internal void OnOwnerTerminateRemoteHelp()
        {
            if (this.remoteHelpForm != null)
            {
                this.remoteHelpForm.OwnerTeminateHelp();
            }
            else
            {
                this.AppendSysMessage("对方取消了远程协助请求。");               
                this.skinTabControl1.TabPages.RemoveAt(this.GetSelectIndex(this.Title_RemoteHelp));
                this.skinTabControl1.SelectedIndex = this.skinTabControl1.TabPages.Count - 1;
            }
        }

        /// <summary>
        /// 【站在请求方角度】协助方关闭了远程桌面
        /// </summary>
        internal void OnHelperCloseRemoteHelp()
        {
            this.AppendSysMessage("对方断开了到您桌面的连接。");
            this.remoteHelpHandlePanel.OnTerminate();
            this.skinTabControl1.TabPages.RemoveAt(this.GetSelectIndex(this.Title_RemoteHelpHandle));
            this.skinTabControl1.SelectedIndex = this.skinTabControl1.TabPages.Count - 1;
        }

        /// <summary>
        /// 作为协助方，对远程协助请求的应答。（点击控件的按钮）
        /// </summary>       
        void remoteHelpRequestPanel_RemoteHelpRequestAnswerd(bool agree)
        {
            this.skinTabControl1.TabPages.RemoveAt(this.GetSelectIndex(this.Title_RemoteHelp));
            this.skinTabControl1.SelectedIndex = this.skinTabControl1.TabPages.Count - 1;

            this.rapidPassiveEngine.CustomizeOutter.Send(this.friendID, agree ? InformationTypes.AgreeRemoteHelp : InformationTypes.RejectRemoteHelp, null);

            string showText = string.Format("您{0}了对方的远程协助请求。", agree ? "同意" : "拒绝");
            this.AppendSysMessage(showText);

            if (agree)
            {
                this.remoteHelpForm = new RemoteHelpForm(this.friendID, this.friendNickName);
                this.remoteHelpForm.RemoteHelpEnded += new CbGeneric<bool>(remoteHelpForm_RemoteHelpEnded);
                this.remoteHelpForm.Show();
            }
        }

        /// <summary>
        /// 远程桌面被关闭。可能原因：1.协助方主动叉掉窗口； 2.请求方终止桌面共享
        /// </summary>       
        void remoteHelpForm_RemoteHelpEnded(bool ownerTerminateClose)
        {
            if (!ownerTerminateClose)
            {
                this.rapidPassiveEngine.CustomizeOutter.Send(this.friendID, InformationTypes.CloseRemoteHelp, null);
            }
            string showText = ownerTerminateClose ? "对方终止了桌面共享。" : "您断开了到对方的远程桌面连接。";
            this.AppendSysMessage(showText);
            this.remoteHelpForm = null;
        }

        /// <summary>
        /// 作为请求方，结束桌面共享。（点击控件的按钮）
        /// </summary>  
        void remoteHelpHandlePanel_RemoteHelpTerminated()
        {
            this.skinTabControl1.TabPages.RemoveAt(this.GetSelectIndex(this.Title_RemoteHelpHandle));
            this.skinTabControl1.SelectedIndex = this.skinTabControl1.TabPages.Count - 1;
            this.rapidPassiveEngine.CustomizeOutter.Send(this.friendID, InformationTypes.TerminateRemoteHelp, null);
            string showText = this.remoteHelpHandlePanel.IsWorking ? "您终止了桌面共享。" : "您取消了远程协助请求。";
            this.AppendSysMessage(showText);
        }       
        #endregion

        #region 离线文件 V3.2
        private void toolStripMenuItem34_Click(object sender, EventArgs e)
        {
            try
            {
                string filePath = ESBasic.Helpers.FileHelper.GetFileToOpen("请选择要发送的离线文件");
                if (filePath == null)
                {
                    return;
                }
                string projectID;               
                SendingFileParas sendingFileParas = new SendingFileParas(2048, 0);//文件数据包大小，可以根据网络状况设定，局网内可以设为204800，传输速度可以达到30M/s以上；公网建议设定为2048或4096或8192

                // BeginSendFile方法
                //（1）accepterID传入null，表示文件的接收者就是服务端
                //（2）巧用comment参数，参见Comment4OfflineFile类
                this.rapidPassiveEngine.FileOutter.BeginSendFile(null, filePath, Comment4OfflineFile.BuildComment(this.friendID), sendingFileParas, out projectID);
                this.FileRequestReceived(projectID);
            }
            catch (Exception ee)
            {                
                MessageBox.Show(ee.Message, "GG");
            }
        } 
        #endregion
        

    }
}
